這是一個鎖匠的故事,在很久很久以前......有兩個鎖匠
就是剛剛講的 isolation level db 預設幫你加上的。
顯式鎖顧名思義就是很明顯看 sql 語句就知道上面有自己加上的鎖。
雖然可以為個別的 tx 加上不同的隔離層級,
但盡量統一隔離層級,如果有特殊需要,自行加上鎖;
大部分的應用都是 Read Committed 中使用 Conflict promotion(下面會解說) + Conflict materialization(下面會解說)。
便足夠了,不建議用更高階的 isolation。
已知大部分的應用都是 Read Committed ,也是大部分 db 預設的 isolation level,
也已知寫操作
都會加上互斥鎖,讓其他 tx 不可讀不可寫。
所以主要問題在於讀操作(select)
的加鎖。
這裡介紹裡 2 個常用的顯示鎖。
e。g。
select ... for share
select ... for update
select ...
,沒加上任何鎖,讓其他 tx 可以讀,可以寫。select ... for share
,加上共享鎖,讓其他 tx 可以讀,但不可寫。select ... for update
,加上互斥鎖,讓其他 tx 不可讀,且不可寫。在 read commit level 想要讀過不能改,即加上 s lock
e.g. 購物系統中,賣太好,想中途改變價格。
可以看到上面的例子,使用 Read Committed Isolation Level,
回憶上篇 Read Committed 會發生 non-read repeatable,
因為 tx 運行中間可以被 write,
所以,我們加上 select ... for share,禁止其他 tx 做修改,
當有其他 tx 想要 update 時,會被 blocking 住,直到 tx1 commit 之後才可被修改。
在 read commit level 想要插入新資料不造成 rr problem,即加上 x lock
e.g. 商品系統中,想中途改加上該商品的更多細節。
1。 在更改的過程直到 commit,中間所產生的 tx 想要看該商品的 tx 要先 block 住,且不給讀與寫。
2。 正在進行中的不能讀兩次都不同。
該範例為範例 1 的延伸
使用 Read Committed Isolation Level,
並加上 select ... for share,禁止其他 tx 做修改,
這裡我們將專注力移到 tx2,
如果我們想要想中途修改子表,如插入商品資訊,這時就應該將與該商品相關的子表也上鎖。
如果 tx2 使用select ... for share
那麼下個 tx 就會讀到舊的商品細節,這是我們想要避免的爭議。
如果 tx2 使用select ... for update
那麼下個 tx 想要讀取商品細節如附加條件等,就必許等待,就可以安心的插入我們想要操作的子表了。至少後面要完成的訂單都會致依照新的規則。
在操作 db 時,我們會建議盡量讓同一個應用都使用同一個 isolation level,
而非直接看到該應用其中一個最高 isolation level sql 時,就直接將所有 isolation level 做 level up。
可採取該 tx 自己加上較高的 isolation level。
或者再同一個 isolation level 需要依照問題加上共享或互斥鎖。
透過上加上顯示鎖的方式達到相同的效果。
這裡我們先介紹悲觀鎖中的顯式鎖,與上篇的隱式鎖。
下篇我們將介紹第二個鎖匠樂觀鎖
。